﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlTypes;
using Spring.Data.Generic;
using Spring.Data.Common;
using Spring.Data.Objects.Generic;
using Spring.Transaction;
using Kpmg.CompanyInfo;

namespace MySearch
{
    public static class ProfileOM
    {
        public static Profile GetProfile(string profileCode)
        {
            if (string.IsNullOrEmpty(profileCode))
                throw new Exception("ProfileOM.GetProfile::Invalid parameter");

            return ProfileDAO.GetProfile(profileCode);
        }

        public static bool CheckProfileCode(string profileCode)
        {
            if (string.IsNullOrEmpty(profileCode))
                throw new Exception("ProfileOM.CheckProfileCode::Invalid parameter");

            return ProfileDAO.CheckProfileCode(profileCode);
        }

        public static IList<Profile> ListProfile(string staffNo)
        {
            if (string.IsNullOrEmpty(staffNo))
                throw new Exception("ProfileOM.ListProfile::Invalid parameter");

            IList<string> lstCode = ProfileDAO.ListProfileCode(staffNo);

            IList<Profile> list = new List<Profile>();
            foreach (string code in lstCode)
            {
                list.Add(ProfileDAO.GetProfile(code));
            }

            return list;
        }

        public static IList<string> ListProfileCode(string staffNo)
        {
            if (string.IsNullOrEmpty(staffNo))
                throw new Exception("ProfileOM.ListProfileCode::Invalid parameter");

            return ProfileDAO.ListProfileCode(staffNo);
        }

        public static IList<Profile> ListServiceTeamProfile()
        {
            IList<string> lstCode = ProfileDAO.ListServiceTeamProfileCode();

            IList<Profile> list = new List<Profile>();
            foreach (string code in lstCode)
            {
                list.Add(ProfileDAO.GetProfile(code));
            }

            return list;
        }

        public static void CreateProfile(Profile profile, string oper)
        {
            if (profile == null || string.IsNullOrEmpty(oper))
                throw new Exception("ProfileOM.CreateProfile::Invalid parameter");

            if (ProfileDAO.CheckProfileCode(profile.ProfileCode))
                throw new Exception("ProfileOM.CreateProfile::Object exist");

            ProfileDAO.CreateProfile(profile);
            LogUtil.LogEvent(profile.ProfileCode, EventAction.CreateProfile, oper, profile.ToDictionary());
        }

        public static void UpdateProfile(Profile profileNew, string oper, bool isSync = false)
        {
            if (profileNew == null || string.IsNullOrEmpty(oper))
                throw new Exception("ProfileOM.UpdateProfile::Invalid parameter");

            Profile objOld = ProfileDAO.GetProfile(profileNew.ProfileCode);
            if (objOld == null)
                throw new Exception("ProfileOM.UpdateProfile::The object is null");

            IDictionary<string, string> profileDif = profileNew.FindDifference(objOld);
            IDictionary<string, string> memberDif = CheckMemDifference(profileNew, objOld, isSync);
            IDictionary<string, string> fieldDif = CheckDifference(profileNew.Fields.Select(x => x.Value).ToList(), objOld.Fields.Select(x => x.Value).ToList());

            if (profileDif.Count > 0)
            {
                ProfileDAO.UpdateProfile(profileNew, false);
                LogUtil.LogEvent(profileNew.ProfileCode, EventAction.UpdateProfile, oper, profileDif);
            }
            if (memberDif.Count > 0)
            {
                ProfileDAO.UpdateMember(profileNew);
                LogUtil.LogEvent(profileNew.ProfileCode, EventAction.UpdateProfileMember, oper, memberDif);
            }
            if (fieldDif.Count > 0)
            {
                ProfileDAO.UpdateField(profileNew);
                LogUtil.LogEvent(profileNew.ProfileCode, EventAction.UpdateProfileField, oper, fieldDif);
            }
        }

        public static void SyncProfileData(string oper)
        {
            if (string.IsNullOrEmpty(oper))
                throw new Exception("ProfileOM.SyncProfileData::Invalid parameter");

            IDictionary<string, Profile> dicOpp = null;// PmsDataDAO.ListOpportunities();

            try
            {
                foreach (KeyValuePair<string, Profile> objNew in dicOpp)
                {
                    if (!ProfileDAO.CheckProfileCode(objNew.Key))
                    {
                        CreateProfile(objNew.Value, oper);
                    }
                    else
                    {
                        UpdateProfile(objNew.Value, oper, true);
                    }
                }
            }
            catch (Exception e)
            {
                LogUtil.LogEvent("Exception", EventAction.SyncProfile, oper, e.ToString());
            }

        }

        #region private

        private static void SyncOpportunityData(string oper)
        {
            IDictionary<string, Profile> dicOpp = new Dictionary<string, Profile>();// PmsDataDAO.ListOpportunities();

            foreach (KeyValuePair<string, Profile> objNew in dicOpp)
            {
                Profile objOld = ProfileDAO.GetProfile(objNew.Key);
                if (objOld == null)
                {
                    ProfileDAO.CreateProfile(objNew.Value);
                    continue;
                }
                //IDictionary<string, string> dicDiff = objNew.Value.FindDifference(objOld);
                //if (dicDiff.Count > 0)
                //{
                //    if (dicDiff.Keys.Where(x => x.IndexOf(CommonMember) < 0 && x.IndexOf(CompositeField.Prefix) < 0).Count() > 0)
                //    {
                //        ProfileDAO.UpdateProfile(objNew.Value, true);
                //    }
                //    else
                //    {

                //        if (dicDiff.Keys.Where(x => x.IndexOf(CompositeField.Prefix) >= 0).Count() > 0)
                //        {
                //            ProfileDAO.UpdateField(objNew.Value);
                //        }
                //        if (dicDiff.Keys.Where(x => x.IndexOf(CompositeMember.Prefix) >= 0).Count() > 0)
                //        {
                //            ProfileDAO.UpdateMember(objNew.Value);
                //        }

                //    }
                //    LogUtil.LogEvent(objNew.Key, EventAction.UpdateProfile, oper, KpmgObject.DictionaryToString(dicDiff));
                //}

            }
        }

        private static IDictionary<string, string> CheckDifference(IList<CommonField> lstNew, IList<CommonField> lstOld)
        {
            IDictionary<string, string> dicRet = new Dictionary<string, string>();

            foreach (CommonField cf in lstNew)
            {
                if (lstOld.Where(x => (x.Name == cf.Name && x.Value == cf.Value && x.DataType == cf.DataType)).Count() > 0)
                    continue;
                else
                {
                    string key = cf.Name;
                    if (!dicRet.ContainsKey(key))
                        dicRet.Add(key, cf.Value + "," + cf.DataType.ToString());
                }
            }

            return dicRet;
        }

        private static IDictionary<string, string> CheckMemDifference(Profile profileNew, Profile profileOld, bool isSync)
        {
            IDictionary<string, string> dicRet = new Dictionary<string, string>();

            IList<CommonMember> lstSyncNew = profileNew.Members.Select(x => x.Value).Where(x => x.IsSync == true).ToList();
            IList<CommonMember> lstSyncOld = profileOld.Members.Select(x => x.Value).Where(x => x.IsSync == true).ToList();
            IList<CommonMember> lstNotSyncNew = profileNew.Members.Select(x => x.Value).Where(x => x.IsSync == false).ToList();
            IList<CommonMember> lstNotSyncOld = profileOld.Members.Select(x => x.Value).Where(x => x.IsSync == false).ToList();

            if (isSync)
            {
                foreach (CommonMember cm in lstSyncNew)
                {
                    if (lstSyncOld.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role && x.Status == CommonStatus.Active)).Count() > 0)
                        continue;
                    else
                    {
                        CommonMember c = lstSyncOld.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role && x.Status == CommonStatus.Inactive)).FirstOrDefault();
                        if (c != null)
                        {
                            profileNew.AddMember(new CommonMember(c.StaffNo, c.Role, true, CommonStatus.Active));

                            string key = cm.StaffNo + "," + cm.Role.ToString();
                            if (!dicRet.ContainsKey(key))
                                dicRet.Add(key, "Inactive => Active");
                        }
                        else//Old not have, New have
                        {
                            string key = cm.StaffNo + "," + cm.Role.ToString();
                            if (!dicRet.ContainsKey(key))
                                dicRet.Add(key, "new member");
                        }
                    }
                }

                //Add  not sync in old to new
                foreach (CommonMember cm in lstNotSyncOld)
                {
                    profileNew.AddMember(new CommonMember(cm.StaffNo, cm.Role, false, cm.Status));
                }

                IList<CommonMember> lstNew = profileNew.Members.Select(x => x.Value).ToList();
                IList<CommonMember> lstOld = profileOld.Members.Select(x => x.Value).Where(x => x.IsSync == true).ToList();
                //add sync in old to new
                foreach (CommonMember cm in lstOld)
                {
                    if (lstNew.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role)).Count() > 0)
                        continue;

                    profileNew.AddMember(new CommonMember(cm.StaffNo, cm.Role, cm.IsSync, CommonStatus.Inactive));

                    string key = cm.StaffNo + "," + cm.Role.ToString();
                    if (!dicRet.ContainsKey(key))
                        dicRet.Add(key, "Active => Inactive");
                }
            }
            else
            {
                foreach (CommonMember cm in lstNotSyncNew)
                {
                    if (lstNotSyncOld.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role && x.Status == CommonStatus.Active)).Count() > 0)
                        continue;
                    else
                    {
                        CommonMember c = lstNotSyncOld.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role && x.Status == CommonStatus.Inactive)).FirstOrDefault();
                        if (c != null)
                        {
                            profileNew.AddMember(new CommonMember(c.StaffNo, c.Role, false, CommonStatus.Active));

                            string key = cm.StaffNo + "," + cm.Role.ToString();
                            if (!dicRet.ContainsKey(key))
                                dicRet.Add(key, "Inactive => Active");
                        }
                        else//Old not have, New have
                        {
                            string key = cm.StaffNo + "," + cm.Role.ToString();
                            if (!dicRet.ContainsKey(key))
                                dicRet.Add(key, "new member");
                        }
                    }
                }

                //Add sync in old to new
                foreach (CommonMember cm in lstSyncOld)
                {
                    profileNew.AddMember(new CommonMember(cm.StaffNo, cm.Role, true, cm.Status));
                }

                IList<CommonMember> lstNew = profileNew.Members.Select(x => x.Value).ToList();
                IList<CommonMember> lstOld = profileOld.Members.Select(x => x.Value).Where(x => x.IsSync == false).ToList();
                //add not sync in old to new
                foreach (CommonMember cm in lstOld)
                {
                    if (lstNew.Where(x => (x.StaffNo == cm.StaffNo && x.Role == cm.Role)).Count() > 0)
                        continue;

                    profileNew.AddMember(new CommonMember(cm.StaffNo, cm.Role, cm.IsSync, CommonStatus.Inactive));

                    string key = cm.StaffNo + "," + cm.Role.ToString();
                    if (!dicRet.ContainsKey(key))
                        dicRet.Add(key, "Active => Inactive");
                }
            }

            return dicRet;
        }

        #endregion
    }
}
